package top.pengdong.pictureShare.userAuth.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import top.pengdong.pictureShare.common.model.*;
import top.pengdong.pictureShare.common.pojo.RegisterUser;
import top.pengdong.pictureShare.common.utils.Address;
import top.pengdong.pictureShare.userAuth.dao.*;
import top.pengdong.pictureShare.userAuth.entity.*;
import top.pengdong.pictureShare.userAuth.feign.mail.MailFeignServer;
import top.pengdong.pictureShare.userAuth.service.TAuthService;
import top.pengdong.pictureShare.userAuth.service.TUserRoleService;
import top.pengdong.pictureShare.userAuth.service.TUsersService;

@Slf4j
@Service("tUsersService")
public class TUsersServiceImpl extends ServiceImpl<TUsersDao, TUsersEntity> implements TUsersService {

    @Autowired
    private TRoleDao tRoleDao;

    @Autowired
    private TUserRoleDao tUserRoleDao;

    @Autowired
    private TUsersDao tUsersDao;

    @Autowired
    private TAuthDao tAuthDao;

    @Autowired
    private TUserAuthsDao tUserAuthsDao;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MailFeignServer mailFeignServer;


    private String baseUrl = Address.API_DOMAIN;



    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<TUsersEntity> page = this.page(
                new Query<TUsersEntity>().getPage(params),
                new QueryWrapper<TUsersEntity>()
        );
        try {
            // 赋值对应权限操作
            for (TUsersEntity tUsers : page.getRecords()) {
                tUsers.setRole(
                        tRoleDao.selectOne(new QueryWrapper<TRoleEntity>().eq("id",
                                tUserRoleDao.selectOne(new QueryWrapper<TUserRoleEntity>()
                                        .eq("user_id", tUsers.getId())).getRoleId()
                        )).getName()
                );
            }
        } catch (NullPointerException e) {
            // 假如空指针异常判断
        }

        return new PageUtils(page);
    }

    /**
     * 创建用户
     * @param registerUser
     * @return
     */
    @Override
    public R createAccount(RegisterUser registerUser, String ip) {

        // 查看是不是已经注册的用户
        if (checkRegister(registerUser.getMail())) {
            return R.error(ResultCode.REGISTER_MORE.getCode(), ResultCode.REGISTER_MORE.getMsg());
        }

        // 添加用户注册ip请求 限制
        if (redisTemplate.opsForValue().get(SysConstant.IP_RECORD + ip) != null) {
            return R.error(401, "请60s后再次尝试");
        }

        redisTemplate.opsForValue().setIfAbsent(SysConstant.IP_RECORD + "oneday:" + ip, 0L, 1, TimeUnit.DAYS);

        if ((Integer)redisTemplate.opsForValue().get(SysConstant.IP_RECORD  + "oneday:" + ip) > 10) {
            return R.error(401, "当前用户ip被禁用申请");
        }
        redisTemplate.opsForValue().increment(SysConstant.IP_RECORD + "oneday:" + ip);


        // 判断用户名是否存在
        if (getUserByIdentifier(registerUser.getMail(), "邮箱") != null
                || getUserByIdentifier(registerUser.getUsername(), "系统登陆") != null
                //|| !checkRegister(registerUser.getMail())
        ) {
//            System.out.println("用户注册操作失败");
            return R.error(ResultCode.REGISTER_ERROR.getCode(), ResultCode.REGISTER_ERROR.getMsg());
        }

        // 雪花算法生成确认码
        String confirmCode = IdUtil.getSnowflake(1,1).nextIdStr();
        // 盐值
        // String salt = RandomUtil.randomString(6);
        // 加密密码：原始密码 + 盐值
        // String md5Pwd = SecureUtil.md5(registerUser.getPassword() + salt);
        // 激活失效时间 ： 24小时
        Date ldt = new Date();
        // 初始化用户信息
        // registerUser.setSalt(salt);
        registerUser.setPassword(passwordEncoder.encode(registerUser.getPassword()));
        registerUser.setConfirmCode(confirmCode);
        registerUser.setIsValid((byte) 0);
        registerUser.setActivationTime(ldt);

        //新增账号 register 是redis的key值
        try  {
            redisTemplate.opsForValue().set("REGISTER:" + registerUser.getMail(), registerUser, 1, TimeUnit.DAYS);
            // 发送邮件
            String activationUrl = baseUrl + "/api/user/activation?confirmCode=" +
                    confirmCode + "&mail=" + registerUser.getMail();
            mailFeignServer.sendMailForActivationAccount(activationUrl, registerUser.getMail());
            redisTemplate.opsForValue().set(SysConstant.IP_RECORD + ip, 0, 60, TimeUnit.MILLISECONDS);

            return R.ok("发送成功");
        } catch (Exception e){
            e.printStackTrace();
            return R.error(ResultCode.REGISTER_ERROR.getCode(), ResultCode.REGISTER_ERROR.getMsg());
        }
    }

    private boolean checkRegister(String mail) {
        try {
            Object object = redisTemplate.opsForValue().get("REGISTER:" + mail);
            if (object != null) return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }

    /**
     * 查看登陆方式
     * @param username
     * @param type
     */
    private TUserAuthsEntity getUserByIdentifier(String username, String type) {
        return tUserAuthsDao.selectOne(new QueryWrapper<TUserAuthsEntity>()
                .eq("identitytype", type)
                .eq("identifier", username));
    }

    // 验证激活码
    @Transactional
    @Override
    public R activationAccount(String confirmCode, String mail) {
        RegisterUser user = null;
        try {
            user = (RegisterUser) redisTemplate.opsForValue().get("REGISTER:" + mail);
        }catch (Exception e) {

            return R.error(ResultCode.REGISTER_TIME_ERROR.getCode(), URLUtil.encode(ResultCode.REGISTER_TIME_ERROR.getMsg()));
        }
        if (user != null && user.getConfirmCode().equals(confirmCode)) {
            log.info("进行用户注册操作:{}" + user);
            // 查看用户存在与否
            TUsersEntity realUser = tUsersDao.selectOne(new QueryWrapper<TUsersEntity>()
                    .eq("username", user.getUsername()));
            if (realUser == null) {
                realUser = new TUsersEntity();
                realUser.setUsername(user.getUsername());
                realUser.setGender(user.getGender());
                realUser.setAge(user.getAge());
                // 头像添加
                realUser.setEmail(user.getMail());
                realUser.setStatus(1);
                realUser.setNickname(user.getNickname());
                Long insert = (long) tUsersDao.insert(realUser);
                if (insert > 0) {
                    // 添加注册 信息 登陆信息
                    String password = user.getPassword();
                    log.info("用户注册密码加密:{}" + password);
                    TUserAuthsEntity tUserAuthsEntity = new TUserAuthsEntity();
                    tUserAuthsEntity.setUserId(realUser.getId());

                    tUserAuthsEntity.setIdentitytype("系统登陆");
                    tUserAuthsEntity.setIdentifier(user.getUsername());
                    tUserAuthsEntity.setCredential(password);
                    tUserAuthsEntity.setIfverified(1);
                    tUserAuthsDao.insert(tUserAuthsEntity);
                    // 手机登录方式
                    if (user.getCellphone() != null) {
                        TUserAuthsEntity tUserAuthsEntity1 = new TUserAuthsEntity();
                        tUserAuthsEntity1.setIdentitytype("手机");
                        tUserAuthsEntity1.setUserId(realUser.getId());
                        tUserAuthsEntity1.setIdentifier(user.getCellphone());
                        tUserAuthsEntity1.setIfverified(1);
                        tUserAuthsEntity1.setCredential(password);

                        tUserAuthsDao.insert(tUserAuthsEntity1);
                    }
                    // 电话登录方式
                    TUserAuthsEntity tUserAuthsEntity2 = new TUserAuthsEntity();
                    tUserAuthsEntity2.setIdentitytype("邮箱");
                    tUserAuthsEntity2.setIdentifier(user.getMail());
                    tUserAuthsEntity2.setIfverified(1);
                    tUserAuthsEntity2.setUserId(realUser.getId());
                    tUserAuthsEntity2.setCredential(password);

                    tUserAuthsDao.insert(tUserAuthsEntity2);
                    redisTemplate.delete("REGISTER:" + mail);
                    // 添加用户权限
                    TUserRoleEntity tUserRoleEntity = new TUserRoleEntity();
                    // 设置用户角色
                    tUserRoleEntity.setRoleId(3L);
                    tUserRoleEntity.setUserId(realUser.getId());
                    tUserRoleEntity.setStatus(1);
                    tUserRoleDao.insert(tUserRoleEntity);
                    return R.ok(URLUtil.encode("注册成功"));
                }
            } else {
                return R.error(400, URLUtil.encode("用户已经注册了"));
            }
        }
        return R.error(ResultCode.REGISTER_TIME_ERROR.getCode(), URLUtil.encode(ResultCode.REGISTER_TIME_ERROR.getMsg()));
    }

    /**
     * TODO 发现用户分享 转发 收藏等
     * @return
     */
    @Override
    public R findUserInfoTweet(Integer type) {
        return null;
    }

    /**
     * 获取菜单信息
     * @return
     */
    @Override
    public R getMenu(int type) {
        List<TAuthEntity> list = tAuthDao.selectList(
                new QueryWrapper<TAuthEntity>().eq("is_menu", type)
        );
        return R.ok("获取菜单").put("result", list);
    }

    /**
     * 更新用户 信息
     * @param tUsers
     */
    @Transactional
    @Override
    public void updateByIdWithPassword(TUsersEntity tUsers) {
        this.updateById(tUsers);
        // 更改密码
        List<TUserAuthsEntity> tUserAuthsEntity = tUserAuthsDao.selectList(new QueryWrapper<TUserAuthsEntity>()
                .eq("user_id", tUsers.getId()));
        if (tUsers.getPassword() != null)
            for (TUserAuthsEntity tUserAuths : tUserAuthsEntity) {
                tUserAuths.setCredential(passwordEncoder.encode(tUsers.getPassword()));
                tUserAuthsDao.updateById(tUserAuths);
            }
    }
}